/*
   Copyright (c) 2005 Lucas Mello Schnorr <schnorr@gmail.com>
   
   This file is part of DIMVisual.
   
   DIMVisual is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.
   
   DIMVisual is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   for more details.
   
   You should have received a copy of the GNU Lesser General Public License
   along with DIMVisual; if not, write to the Free Software Foundation, Inc.,
   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include "AllToOne.h"

@implementation AllToOne
- (id) init
{
	self = [super init];
	operations = [[NSMutableArray alloc] init];
	key = 0;
	return self;
}

- (void) dealloc
{
	[operations release];
	[super dealloc];
}

- (int) searchForMemberEntering: (NSString *) member withKey: (NSString *) myKey
{
	int flag = -1, i;

//	NSLog (@"ENTER Search for key %@", myKey);
	for (i = 0; i < [operations count]; i++){
		if ([myKey isEqual: [[operations objectAtIndex: i] objectForKey: @"key"]]){
//			NSLog (@"ENTER %d,%@:%@",i,myKey, [operations objectAtIndex: i]);
			if (![[[operations objectAtIndex: i] objectForKey: @"members"] containsObject: member]){ /* does not contain */
//				NSLog (@"found place for %@ at %d", member,i);
				flag = i;
				break;
				
			}
		}
	}
//	NSLog (@"ENTER #%d#%@", flag, operations);
	return flag;
}

- (int) searchForMemberExiting: (NSString *) member withKey: (NSString *) myKey
{
	int flag = -1, i;
//	NSLog (@"EXIT search for member %@ with key %@",member,myKey);
	for (i = 0; i < [operations count]; i++){
		if ([myKey isEqual: [[operations objectAtIndex: i] objectForKey: @"key"]]){
//			NSLog (@"EXIT %d,%@:%@",i,myKey, [operations objectAtIndex: i]);
			if ([[[operations objectAtIndex: i] objectForKey: @"members"] containsObject: member]){ /* contains */
//				NSLog (@"found %@ at %d", member,i);
				flag = i;
				break;
			}
		}
	}
//	NSLog (@"EXIT #%d#%@", flag, operations);
	return flag;
}


- (void) memberEntering: (NSString *) member
	andEventNode: (NSString *) eventNode
	andEventTime: (NSString *) eventTime
	andRootNode: (NSString *) rootNode
	andCommSize: (NSString *) commSize
	andMembersId: (NSString *) membersNode
{
	int flag;
//	int i;
	NSString *myKey;
	myKey = [NSString stringWithFormat: @"%@_%@", membersNode, rootNode];
	flag = [self searchForMemberEntering: member withKey: myKey];

	if (flag == -1){ /* place not found, allocate one for me */
		NSMutableDictionary *x;
		NSMutableArray *y;
		x = [[NSMutableDictionary alloc] init];
		y = [[NSMutableArray alloc] init];
		[y addObject: member];
		[x setObject: myKey forKey: @"key"];
		[x setObject: y forKey: @"members"];
		[x setObject: commSize forKey: @"size"];
		[x setObject: eventTime forKey: member];
		[y release];
		[operations addObject: x];
		flag = [operations indexOfObject: x];
//		NSLog (@"CREATED NEW ENTRY %@", x);
		[x release];
	}else{
		[[[operations objectAtIndex: flag] objectForKey: @"members"] addObject: member];
		[[operations objectAtIndex: flag] setObject: eventTime forKey: member];
	}
	if ([rootNode isEqual: eventNode]){
		[[operations objectAtIndex: flag] setObject: member forKey: @"root"];
	}
}

- (NSMutableArray *) memberExiting: (NSString *) member
	andEventTime: (NSString *) eventTime
	andOperationName: (NSString *) operName
	andRootNode: (NSString *) rootNode
	andMembersId: (NSString *) membersNode
	andProvider: (id<Integrator>) provider
{
//	static int k = 0;
//	int i;
	int flag;
	NSMutableArray *ret;

	
	ret = [[NSMutableArray alloc] init];

	NSString *myKey;
	myKey = [NSString stringWithFormat: @"%@_%@", membersNode, rootNode];
	flag = [self searchForMemberExiting: member withKey: myKey];

	if (flag == -1){
		NSLog (@"flag is -1 (%@)", myKey);
		NSLog (@"%@", operations);
		exit(1);
		[ret autorelease];
		return ret;
	}

	NSString *root = [[operations objectAtIndex: flag]
		objectForKey: @"root"];

	if ([member isEqual: root] && root != nil){

		if ([[[operations objectAtIndex: flag] objectForKey: @"members"] count] != [[[operations objectAtIndex: flag] objectForKey: @"size"] intValue]){
			NSLog (@"ERROR %@", [operations objectAtIndex: flag]);
			exit(1);
		}

//		NSLog (@"%@", [operations objectAtIndex: flag]);
		NSMutableArray *x = [[operations objectAtIndex: flag] objectForKey: @"members"];
		NSEnumerator *enumerator = [x objectEnumerator];
		NSString *oneMember;
		while ((oneMember = [enumerator nextObject])){
			NSLog (@"(%@)Link from %@(%@) to %@(%@)",myKey,
					oneMember, [[operations objectAtIndex: flag] objectForKey: oneMember],	member, eventTime);
			PajeStartLink *sl;
			sl = [[PajeStartLink alloc] init];
			[sl setTime: [[operations objectAtIndex: flag] objectForKey: oneMember]];
			[sl setContainer: [provider identifierForEntity: [NSArray arrayWithObjects: @"0", nil] ids: [NSArray arrayWithObjects: @"0", nil]]];
			[sl setSourceContainer: oneMember];
			[sl setEntityType: [provider aliasToName:@"MPICommunication"]];
			[sl setValue: [provider aliasToName: operName]];
			[sl setKey: [NSString stringWithFormat: @"%@%d",operName,key]];
	                
			PajeEndLink *el;
			el = [[PajeEndLink alloc] init];
			[el setTime: eventTime];
			[el setContainer: [provider identifierForEntity: [NSArray arrayWithObjects: @"0", nil] ids: [NSArray arrayWithObjects: @"0", nil]]];
			[el setDestContainer: member];
			[el setEntityType: [provider aliasToName:@"MPICommunication"]];
			[el setValue: [provider aliasToName: operName]];
			[el setKey: [NSString stringWithFormat: @"%@%d",operName,key]];
                        
			[ret addObject: sl];
			[ret addObject: el];
			[sl release];
			[el release];
                        
			key++;
		}
//		NSLog (@"REMOVING %@", [operations objectAtIndex: flag]);
//		[operations removeObjectAtIndex: flag];
//		NSLog (@"REMOVED");
	}else{
//		NSLog (@"HI %@",root);
	}

	[ret autorelease];
	return ret;
}
@end
